<template>
  <SearchForm v-if="showSearch" :formData="formData" @searchSubmit="searchSubmit"></SearchForm>
  <!-- 表格 -->
  <div class="component_table">
    <div class="table_handle">
      <div class="table_handle_btn">
        <el-button
          v-if="apiUrl.add"
          v-hasPermi="permission.add"
          type="primary"
          size="large"
          plain
          icon="plus"
          @click="handleAdd"
          >新增</el-button
        >
        <el-button
          v-if="choiceColumn && apiUrl.edit"
          v-hasPermi="permission.edit"
          :disabled="single"
          type="warning"
          size="large"
          plain
          icon="Edit"
          @click="handleEdit"
          >编辑</el-button
        >
        <el-button
          v-if="choiceColumn && apiUrl.del"
          v-hasPermi="permission.del"
          :disabled="multiple"
          type="danger"
          size="large"
          plain
          icon="Delete"
          @click="confirmEvent"
          >删除</el-button
        >
        <el-button
          v-if="apiUrl.export"
          v-hasPermi="permission.export"
          type="info"
          size="large"
          plain
          icon="Download"
          >导出</el-button
        >
      </div>
      <div class="table_handle_btn">
        <el-tooltip content="点击刷新">
          <el-button @click="refresh" icon="Refresh" color="#626aef" circle />
        </el-tooltip>
      </div>
    </div>
    <el-table
      :data="tableData"
      v-loading="isLoading"
      v-loading.fullscreen="isLoadingFull"
      :row-key="rowKey"
      :default-sort="defaultSort"
      @selection-change="handleTableSelect"
      @sort-change="handleSortChange"
      :tree-props="{ children: 'children' }"
    >
      <el-table-column type="selection" width="55" v-if="choiceColumn" />
      <el-table-column
        v-for="(item, index) in columns"
        :key="index"
        :prop="item.prop"
        :label="item.label"
        :width="item.width"
        :align="item.align"
        :sortable="item.sortable"
        class-name="component_table_column"
      >
        <template #default="scoped">
          <template v-if="$slots[item.prop]">
            <slot :name="item.prop" :row="scoped.row" :index="scoped.$index" />
          </template>
          <span v-else>{{ scoped.row[item.prop] }}</span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center" v-if="showHandle">
        <template #default="scoped">
          <slot
            v-if="$slots['handle']"
            name="handle"
            :index="'handle' + scoped.$index"
            :row="scoped.row"
            :list="tableData"
          ></slot>
          <el-button
            type="primary"
            icon="Edit"
            size="small"
            @click="handleEdit(scoped.row)"
            circle
            v-if="apiUrl.edit"
            v-hasPermi="permission.edit"
          />
          <el-popconfirm
            v-if="apiUrl.del"
            title="确认删除此条？"
            confirm-button-text="确定"
            cancel-button-text="取消"
            placement="bottom-end"
            @confirm="confirmEvent(scoped.row)"
          >
            <template #reference>
              <el-button
                v-hasPermi="permission.del"
                type="danger"
                icon="Delete"
                size="small"
                circle
              />
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
      <template #empty>
        <el-empty description="没有数据哦">
          <el-tooltip content="点击刷新">
            <el-button @click="refresh" size="large" type="danger" icon="RefreshRight" circle />
          </el-tooltip>
        </el-empty>
      </template>
    </el-table>
    <div class="component_table_pagination" v-if="showPage">
      <el-pagination
        v-model:current-page="tableArg.data.page"
        v-model:page-size="tableArg.data.limit"
        :page-sizes="[2, 10, 20, 40, 50]"
        :background="pagination.background"
        :layout="pagination.layout"
        :total="total"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
      />
    </div>
    <!-- Form -->
    <!-- size="50%" -->
    <el-drawer
      class="drawer_form"
      :class="{'editor_has':hasEditor}"
      v-model="drawer.val"
      :title="drawer.title"
      @open="handleOpen"
      :before-close="handleClose"
    >
      <Form
        ref="formRef"
        :formData="formData"
        :apiUrl="apiUrl"
        :formShow="formShow"
        @submitReset="refresh(1)"
      ></Form>
    </el-drawer>
  </div>
</template>

<script setup name="Table">
import Form from "@/components/Form/index";
import SearchForm from "@/components/SearchForm/index";
import { onMounted, reactive } from "vue";
const { proxy } = getCurrentInstance();
/**
 * choiceColumn: 是否显示选择框
 * apiUrl: 接口地址
 * columns: 表头：{
 *   prop: 表头字段
 *   label: 表头名称
 *   width: 表头宽度
 *   align: 表头对齐方式
 * }
 * rowKey: 表格主键
 * emitUpStatus: 是否传递表格数据 回调回父组件操作
 * formData: 表单数据
 * formShow 根据规则显示表单
 * showHandle: 是否显示操作按钮
 * showPage: 是否显示分页
 * showwSearch: 是否显示搜索框
 * hasEditor 表单是否存在编辑器
 * permission 权限控制
 * defaultSort  默认排序
 */
const props = defineProps({
  choiceColumn: { type: Boolean, default: false },
  apiUrl: { type: Object, default: {} },
  columns: { type: Array, default: [] },
  formData: { type: Array, default: [] },
  formShow: { type: String, default: "1" },
  rowKey: { type: String, default: "id" },
  emitUpStatus: { type: Boolean, default: false },
  showHandle: { type: Boolean, default: true },
  showPage: { type: Boolean, default: false },
  showSearch: { type: Boolean, default: true },
  hasEditor: { type: Boolean, default: false },
  permission: { type: Object, default: {} },
  defaultSort: { type: Object, default: {} },
});

const pagination = reactive({
  layout: "total, sizes, prev, pager, next, jumper",
  background: true,
});

const drawer = ref({
  val: false,
  title: "",
});
const formRef = ref();
const formOption = ref({});

const isLoading = ref(false);
const isLoadingFull = ref(false);
const ids = ref([]);
const single = ref(true);
const multiple = ref(true);
const total = ref(0);
const tableArg = reactive({
  data: { sort: props.defaultSort },
});
const tableData = ref([]);

const emit = defineEmits(["update:formData", "openFormBefore"]);

/**
 * 初始化
 */
onMounted(() => {
  refresh();
});

watch(
  () => props.showPage,
  (newVal) => {
    if (newVal) {
      tableArg.data = {
        page: 1,
        limit: 10,
        sort: props.defaultSort,
      };
    }
  },
  { immediate: true }
);

// 获取表格数据
const getTableData = (callBack) => {
  isLoading.value = true;
  props.apiUrl
    .list(tableArg.data)
    .then((res) => {
      tableData.value = res.data.rows;
      total.value = res.data.total;
      // 回调
      if (callBack && typeof callBack === "function") {
        callBack(res.data.rows);
      }
    })
    .finally(() => {
      isLoading.value = false;
    });
};
/**
 * 表格回调更新数据
 */
const updateCallBack = () => {
  getTableData((data) => {
    emit("update:formData", data);
  });
};
/**
 * 刷新表格
 */
const refresh = (type = 0) => {
  if (props.emitUpStatus) {
    updateCallBack();
  } else {
    getTableData();
  }
  if (type) drawer.value.val = false;
};

/**
 * 修改弹框
 * @param val 修改id
 */
const handleEdit = (val) => {
  let id = val.id || ids.value;
  isLoadingFull.value = true;
  props.apiUrl
    .get({ id })
    .then((res) => {
      // isLoadingFull.value = false;
      if (res.code == 200) {
        drawer.value.val = true;
        drawer.value.title = "修改";
        formOption.value = res.data;
      }
    })
    .finally(() => {
      isLoadingFull.value = false;
    });
};
/**
 * 删除
 * @param row 删除id
 */
const confirmEvent = (row) => {
  let id = row.id || ids.value;
  isLoading.value = true;
  props.apiUrl
    .del({ id })
    .then((res) => {
      if (res.code == 200) {
        proxy.$notify({
          title: "删除成功，刷新页面中...",
          message: "编号为" + id + "的数据删除成功",
          type: "success",
        });
        refresh();
      }
    })
    .catch(() => {
      isLoading.value = false;
    });
};
/**
 * 修改状态
 */
const handleTableData = (val) => {
  proxy.$msgbox({
    title: "修改",
    message: "确定修改编号为" + val.id + "的数据吗？",
    showCancelButton: true,
    confirmButtonText: "确定",
    cancelButtonText: "取消",
    type: "warning",
    callback: (action) => {
      if (action == "confirm") {
        isLoading.value = true;
        props.apiUrl
          .edit(val)
          .then((res) => {
            refresh();
            if (res.code == 200) {
              proxy.$notify({
                title: "修改成功，等待刷新...",
                message: "编号为" + val.id + "的数据修改成功",
                type: "success",
              });
            }
          })
          .catch(() => {
            isLoading.value = false;
          });
      } else {
        val.status = val.status ? 0 : 1;
      }
    },
  });
};
/**
 * @param val 搜索参数
 */
const searchSubmit = (val) => {
  tableArg.data = props.showPage
    ? {sort:tableArg.data.sort, page: tableArg.data.page, limit: tableArg.data.limit, ...val }
    : { ...val };

  refresh();
};
/**
 * 新增
 */
const handleAdd = () => {
  formOption.value = {};
  props.formData.forEach((item) => {
    if (!item.hasOwnProperty("showRule") || item.showRule.includes(props.formShow))
      formOption.value[item.prop] = item.default;
  });
  drawer.value.val = true;
  drawer.value.title = "新增";
};
/**
 * 打开弹窗回调
 */
const handleOpen = () => {
  emit("openFormBefore", formOption.value);
  formRef.value.initFormData(formOption.value);
};
/**
 * 表格选择
 */
const handleTableSelect = (val) => {
  ids.value = val.map((item) => item.id);
  single.value = val.length != 1;
  multiple.value = !val.length;
};

/**
 * 表格排序
 */
const handleSortChange = (val) => {
  if (val.order != null) {
    tableArg.data.sort = { prop: val.prop, order: val.order };
  } else {
    tableArg.data.sort = {};
  }
   getTableData();
};
/**
 * 分页
 */
const handleSizeChange = (val) => {
  tableArg.data.limit = val;
  getTableData();
};
/**
 * 分页
 */
const handleCurrentChange = (val) => {
  tableArg.data.page = val;
  getTableData();
};
// Form
const handleClose = () => {
  drawer.value.val = false;
};

defineExpose({ handleAdd, handleTableData });
</script>

<style lang="scss">
.component_table {
  .el-table {
    width: 100%;

    .component_table_column {
      padding: 15px 0;
    }

    .el-table__header {
      th.el-table__cell {
        background: var(--el-fill-color-light);
      }
    }
  }
}
/* 小屏幕下全宽度 */
@media (max-width: 768px) {
  .el-drawer.drawer_form {
    width: 100% !important;
  }
}
/* 小屏幕下全宽度 */
@media (min-width: 768px) {
  .el-drawer.drawer_form {
    width: 60% !important;
  }
}
/* 中等屏幕60%宽度 */
@media (min-width: 1200px) {
  .el-drawer.drawer_form {
    width: 40% !important;
  }
  .el-drawer.editor_has {
    width: 60% !important;
  }
}
</style>
<style scoped lang="scss">
.component_table {
  background: var(--box-back-color);
  box-shadow: var(--dark-shadow-001ad4);
  border-radius: 8px;
  &_pagination {
    @include flexBox(row, flex-end, center);
    padding: 15px 20px;
  }
}

.table_handle {
  @include flexBox(row, space-between, center);
  padding: 20px 20px 15px;
}
</style>
